<template>
  <ElDialog v-model="visible" title="菜单权限" width="520px" align-center class="el-dialog-border" @close="handleClose">
    <ElScrollbar height="70vh">
      <ElTree ref="treeRef" :data="processedMenuList" show-checkbox node-key="id" :default-expand-all="isExpandAll"
        :props="defaultProps" @check="handleTreeCheck">
        <template #default="{ data }">
          <div style="display: flex; align-items: center">
            <span>{{ defaultProps.label(data) }}</span>
          </div>
        </template>
      </ElTree>
    </ElScrollbar>
    <template #footer>
      <div class="dialog-footer">
        <ElButton @click="outputSelectedData" style="margin-left: 8px">获取选中数据</ElButton>

        <ElButton @click="toggleExpandAll">{{ isExpandAll ? '全部收起' : '全部展开' }}</ElButton>
        <ElButton @click="toggleSelectAll" style="margin-left: 8px">{{
          isSelectAll ? '取消全选' : '全部选择'
        }}</ElButton>
        <ElButton type="primary" @click="savePermission">保存</ElButton>
      </div>
    </template>
  </ElDialog>
</template>

<script setup lang="ts">
import { fetchRolePermissions, updateRolePermissions } from '@/api/system/role'
import { nextTick } from 'vue'
import { fetchGetAllMenuTree } from '@/api/system-manage'
import type { AppRouteRecord } from '@/types/router'

type RoleListItem = Api.SystemManage.RoleListItem

interface Props {
  modelValue: boolean
  roleData?: RoleListItem
}

interface Emits {
  (e: 'update:modelValue', value: boolean): void
  (e: 'success'): void
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: false,
  roleData: undefined
})

const emit = defineEmits<Emits>()

const visible = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})


const treeRef = ref()
const isExpandAll = ref(true)
const isSelectAll = ref(false)
const menuTree = ref<AppRouteRecord[]>([])

// 将后端菜单树中的 auth_list 合并为树的子节点，保留菜单结构
const processedMenuList = computed(() => {
  const transformNode = (n: AppRouteRecord): any => {
    const childrenMenus = Array.isArray(n.children) ? n.children.map(transformNode) : []
    const buttonChildren = Array.isArray(n.meta?.authList)
      ? n.meta!.authList!.map((b: any) => ({
        id: b.id,
        name: b.title,
        code: b.authMark,
        type: 2,
        sort: 0,
        status: true,
        children: []
      }))
      : []

    return {
      id: n.id,
      name: n.meta?.title || n.name,
      code: (n as any).meta?.code || n.name,
      type: 1,
      sort: (n as any).meta?.sort ?? 0,
      status: true,
      children: [...childrenMenus, ...buttonChildren]
    }
  }

  return Array.isArray(menuTree.value) ? menuTree.value.map(transformNode) : []
})

const defaultProps = {
  children: 'children',
  label: (data: any) => data?.name || data?.meta?.title || ''
}

// 监听弹窗打开，初始化权限数据
watch(
  () => props.modelValue,
  (newVal) => {
    if (newVal && props.roleData) {
      // 加载后端菜单树与角色权限，并设置默认选中
      loadPermissions()
    }
  }
)

const handleClose = () => {
  visible.value = false
  treeRef.value?.setCheckedKeys([])
}

const savePermission = async () => {
  const tree = treeRef.value
  if (!tree || !props.roleData?.id) return

  const checkedKeys: (number | string)[] = tree.getCheckedKeys()
  const halfCheckedKeys: (number | string)[] = tree.getHalfCheckedKeys()
  // 合并半选与全选的节点 id，去重后提交
  const permissionIds = Array.from(new Set([...checkedKeys, ...halfCheckedKeys]))
    .filter((k) => typeof k === 'number') as number[]

  try {
    await updateRolePermissions(props.roleData.id, permissionIds)
    ElMessage.success('权限保存成功')
    emit('success')
    handleClose()
  } catch (error) {
    console.error('保存权限失败:', error)
  }
}

const toggleExpandAll = () => {
  const tree = treeRef.value
  if (!tree) return

  // 使用store.nodesMap直接控制所有节点的展开状态
  const nodes = tree.store.nodesMap
  Object.values(nodes).forEach((node: any) => {
    node.expanded = !isExpandAll.value
  })

  isExpandAll.value = !isExpandAll.value
}

const toggleSelectAll = () => {
  const tree = treeRef.value
  if (!tree) return

  if (!isSelectAll.value) {
    // 全选：获取所有节点的key并设置为选中
    const allKeys = getAllNodeKeys(processedMenuList.value)
    tree.setCheckedKeys(allKeys)
  } else {
    // 取消全选：清空所有选中
    tree.setCheckedKeys([])
  }

  isSelectAll.value = !isSelectAll.value
}

const getAllNodeKeys = (nodes: any[]): (number | string)[] => {
  const keys: (number | string)[] = []
  const traverse = (nodeList: any[]) => {
    nodeList.forEach((node) => {
      if (node.id !== undefined) {
        keys.push(node.id)
      }
      if (node.children && node.children.length > 0) {
        traverse(node.children)
      }
    })
  }
  traverse(nodes)
  return keys
}

const handleTreeCheck = () => {
  const tree = treeRef.value
  if (!tree) return

  // 使用树组件的getCheckedKeys方法获取选中的节点
  const checkedKeys = tree.getCheckedKeys()
  const allKeys = getAllNodeKeys(processedMenuList.value)

  // 判断是否全选：选中的节点数量等于总节点数量
  isSelectAll.value = checkedKeys.length === allKeys.length && allKeys.length > 0
}

// 输出选中的数据
const outputSelectedData = () => {
  const tree = treeRef.value
  if (!tree) return

  // 获取选中的节点keys
  const checkedKeys = tree.getCheckedKeys()
  // 获取半选中的节点keys（父节点部分选中时）
  const halfCheckedKeys = tree.getHalfCheckedKeys()
  // 获取选中的节点数据
  const checkedNodes = tree.getCheckedNodes()
  // 获取半选中的节点数据
  const halfCheckedNodes = tree.getHalfCheckedNodes()

  const selectedData = {
    checkedKeys,
    halfCheckedKeys,
    checkedNodes,
    halfCheckedNodes,
    totalChecked: checkedKeys.length,
    totalHalfChecked: halfCheckedKeys.length
  }

  console.log('=== 选中的权限数据 ===', selectedData)
  ElMessage.success(`已输出选中数据到控制台，共选中 ${checkedKeys.length} 个节点`)
}

// 加载菜单树与角色权限
const loadPermissions = async () => {
  try {
    // 获取完整菜单树（已转换为前端路由结构，按钮聚合到 meta.authList）
    const data = await fetchGetAllMenuTree()
    const list = (data as any).menuList ?? (data as any).items ?? []
    menuTree.value = Array.isArray(list) ? list : []

    if (props.roleData?.id) {
      const rolePerm = await fetchRolePermissions(props.roleData.id)
      const keys = rolePerm.permission_ids || []
      // 设置已选权限
      nextTick(() => {
        treeRef.value?.setCheckedKeys(keys)
        handleTreeCheck()
      })
    }
  } catch (error) {
    console.error('加载权限数据失败:', error)
  }
}
</script>

<style lang="scss" scoped>
.dialog-footer {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
}
</style>
